package com.lrh.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lrh.reggie.common.R;
import com.lrh.reggie.dto.DishDto;
import com.lrh.reggie.dto.SetmealDto;
import com.lrh.reggie.entity.Setmeal;
import com.lrh.reggie.service.CategoryService;
import com.lrh.reggie.service.SetmealDishService;
import com.lrh.reggie.service.SetmealService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 套餐管理
 *
 * Spring Cache缓存
 * 在启动类上加入@EnableCaching注解，开启缓存功能
 * @CacheEvict :应用到移除数据的方法上，如删除方法，调用方法时会从缓存中移除相应的数据
 * @Cacheable ：应用到读取数据的方法上，即可缓存的方法，如查找方法，先从缓存中读取，
 *   如果没有再调用相应方法获取数据，然后把数据添加到缓存中
 * @CachePut :应用到写数据的方法上，如新增/修改方法，调用方法时会自动把相应的数据放入缓存
 *
 */
@Slf4j
@RestController
@RequestMapping("/setmeal")
public class SetmealController {

    @Autowired
    private SetmealService setmealService;

    @Autowired
    private SetmealDishService setmealDishService;

    /**
     * 新增套餐
     *
     * @param setmealDto
     * @return
     */
    @PostMapping
    // allEntries 表示删除 setmealCache 分类下的所有缓存数据
    @CacheEvict(value = "setmealCache",allEntries = true)
    public R<String> save(@RequestBody SetmealDto setmealDto) {
        log.info("套餐信息:{}", setmealDto);

        setmealService.saveWithSetmealDish(setmealDto);

        return R.success("新增套餐成功");
    }

    /**
     * 套餐信息分页查询
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize, String name) {

        log.info("page:{},pageSize:{},name:{}", page, pageSize, name);

        Page<SetmealDto> allPage = setmealService.getAllPage(page, pageSize, name);

        return R.success(allPage);
    }


    /**
     * 删除套餐和该套餐菜品关系的数据
     *
     * @param ids
     * @return
     */
    @DeleteMapping
    // allEntries 表示删除 setmealCache 分类下的所有缓存数据
    @CacheEvict(value = "setmealCache",allEntries = true)
    public R<String> delete(String ids) { //也可以用List<Long> ids 接收
        log.info("ids:{}", ids);

        setmealService.removeWithSetmealDish(ids);

        return R.success("删除成功");
    }

    /**
     * 修改套餐售卖状态
     *
     * @param status
     * @param ids
     * @return
     */
    @PostMapping("/status/{status}")
    // allEntries 表示删除 setmealCache 分类下的所有缓存数据
    @CacheEvict(value = "setmealCache",allEntries = true)
    public R<String> statusHandle(@PathVariable int status, String ids) {
        log.info("售卖套餐状态：{}，售卖套餐id：{}", status, ids);

        setmealService.updateStatus(status, ids);

        return R.success("修改成功");
    }


    /**
     * 套餐管理的修改套餐的数据回显
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    // allEntries 表示删除 setmealCache 分类下的所有缓存数据
    @CacheEvict(value = "setmealCache",allEntries = true)
    public R<SetmealDto> getSetmealDish(@PathVariable Long id) {
        log.info("id:{}", id);

        SetmealDto setmealDto = setmealService.getByIdWithSetmealDish(id);

        return R.success(setmealDto);
    }

    /**
     * 修改套餐,需要修改套餐和菜品的关联关系
     *
     * @param setmealDto
     * @return
     */
    @PutMapping
    // allEntries 表示删除 setmealCache 分类下的所有缓存数据
    @CacheEvict(value = "setmealCache",allEntries = true)
    public R<String> update(@RequestBody SetmealDto setmealDto) {
        log.info("setmealDto：{}", setmealDto);

        setmealService.updateWithSetmealDish(setmealDto);
        return R.success("修改成功");
    }


    /**
     * 用户端 套餐分类  对应的套餐  eg.这个套餐分类里有那些套餐
     *
     * Spring Cache 缓存 可以对redis进行代码简化
     * @param status
     * @param categoryId
     * @return
     */
    @GetMapping("/list")
    @Cacheable(value = "setmealCache",key = "#categoryId + '_' + #status") //SPEL语法
    // @Cacheable 在方法执行前spring先查看缓存中是否有数据，如果有数据，则直接返回缓存数据;
    // 若没有数据，调用方法并将方法返回值放到缓存中
//    这里方法返回的结果R，它的类需要实现序列化接口，否则会报错，无法缓存。
    public R<List<Setmeal>> setmealList(int status, Long categoryId) {

        log.info("status:{},categoryId:{}", status, categoryId);

        LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Setmeal::getCategoryId, categoryId);

        List<Setmeal> setmealList = setmealService.list(lambdaQueryWrapper);

        return R.success(setmealList);
    }


    /**
     * 用户端 套餐分类的 套餐里的菜品展示
     *
     * @param id
     * @return
     */
    @GetMapping("/dish/{id}")
    public R<List<DishDto>> setmealDishList(@PathVariable Long id) {  //修改后
//    public R<List<SetmealDish>> setmealDishList(@PathVariable Long id){
    // public R<List<SetmealDish>> setmealDishList(@PathVariable Long id){
    // 这样做会导致 用户端 套餐分类的 套餐里的菜品展示 时菜品的图片无法展示

        log.info("id:{}", id); // 前端传的id是套餐的id
//        List<SetmealDish> userSetmealDishList = setmealDishService.getUserSetmealDish(id);
//        return R.success(userSetmealDishList);
        List<DishDto> dishDtoList = setmealDishService.setmealDishList(id);

        return R.success(dishDtoList);
    }

}
